// 交易共识：验证单个交易的算法，包含签名验证和 UTXO 验证。
// UTXO 验证：交易输入引用的 未花费交易输出（UTXO） 是否有效。若输入已被其他交易（如 TX-A）花费，则新收到的交易会被判定为无效。

use thiserror::Error;

use bc_base::{TransactionId, script::ScriptError, transaction::TransactionError};

mod orphan_txs;
mod transaction_impl;
mod transaction_index;
mod tx_mem_pool;

use transaction_index::TransactionIndexError;

pub(super) use transaction_impl::TransactionConsensus;

#[derive(Error, Debug, PartialEq)]
pub enum TransactionConsensusError {
    #[error("Transaction not found")]
    TransactionNotFound,

    // transaction not found in the pool
    #[error("Transaction not found in the pool")]
    TransactionNotFoundInPool,

    // transaction is already in the pool
    #[error("Transaction is already in the pool")]
    TransactionAlreadyInPool,

    // transaction is already in the disk
    #[error("Transaction is already in the disk")]
    TransactionAlreadyInDisk(TransactionId),

    // miss input of the transaction
    #[error("Miss input of the transaction")]
    MissTransactionInput,

    // orphan transaction is already exists
    #[error("Orphan transaction is already exists")]
    OrphanTransactionAlreadyExists,

    // orphan transaction not found
    #[error("Orphan transaction not found")]
    OrphanTransactionNotFound(TransactionId),

    // transaction index is already exists
    #[error("Transaction index is already exists")]
    TransactionIndexAlreadyExists,

    // double spending of the same UTXO in transaction pool
    #[error("Double spending of the same UTXO in transaction pool")]
    DoubleSpendingUTXOInTxPool,

    // Coinbase is only valid in a block, not as a loose transaction
    #[error("Coinbase is only valid in a block, not as a loose transaction")]
    CoinbaseInLooseTransaction,

    // The index in prev outpoint is out of range
    #[error("The index in prev outpoint is out of range")]
    OutpointIndexOutOfRange,

    #[error("Coinbase Not Mature")]
    CoinbaseNotMature,

    #[error("Invalid Signature")]
    InvalidSignature,

    #[error("Insufficient Fee")]
    InsufficientFee,

    #[error("Negative Fee")]
    NegativeFee,

    #[error("Prev Tx Index Not Found")]
    PrevTxIndexNotFound,

    #[error("Outpoint Already Spent")]
    UtxoAlreadySpent,

    // TransactionIndexError
    #[error("TransactionIndexError")]
    TransactionIndexError(#[from] TransactionIndexError),

    #[error("Transaction Error from bc_base")]
    TxError(#[from] TransactionError),

    #[error("Script Error from bc_base")]
    ScriptError(#[from] ScriptError),

    #[error("TopStorageError")]
    TopStorageError(#[from] bc_lib::top_storage::TopStorageError),

    // BestHeightNotFound
    #[error("Best Height Not Found")]
    BestHeightNotFound,
}
